package com.xhwl.centiotdata.integration.vehicleschedule.sinoiov;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.integration.IntegrationZoneException;
import com.xhwl.centiotdata.integration.vehicleschedule.VehicleScheduleIntegrationConfig;
import com.xhwl.centiotdata.integrator.SinoiovIntegrationHandler;
import com.xhwl.centiotdata.integration.vehicleschedule.VehicleScheduleSystemHandler;
import com.xhwl.centiotdata.integrator.vehicleschedule.SinoiovVehicleScheduleResponseDTO;
import com.xhwl.centiotdata.integrator.vehicleschedule.sinoiov.SinoiovStatisticsResponseDTO;
import com.xhwl.centiotdata.integrator.vehicleschedule.sinoiov.TruckQueryResponseDTO;
import com.xhwl.centiotdata.integrator.vehicleschedule.station.StationDTO;
import com.xhwl.common.dto.cent.iotdata.vehicleschedule.*;
import com.xhwl.common.utils.ChkUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Falcon.cao @Copyright (C), 2022, 兴海物联
 * Date: 2022/9/30 15:44
 * Description: 中交兴路 车辆调度系统供应商对接处理
 */
@Slf4j
public class SinoiovVehicleScheduleHandler extends SinoiovIntegrationHandler implements VehicleScheduleSystemHandler {

    private static final String PATH_QUEUE_DETAIL = "getQueueInfo";
    private static final String PATH_TRUCK_EVENTS = "iotTruckEventSync";
    private static final String PATH_ENTER_CHECKS = "iotIsAllowTruckEntry";
    private static final String PATH_WEIGH_EVENTS = "iotWeighingResultSync";
    private static final String PATH_SPACE_STATUS = "iotParkingPlaceStatusSync";

    private static final String PATH_POSITION_TRUCK_QUEUES = "api/iot/queryPositionQueueTruck";
    private static final String PATH_POSITION_TRUCK_DETAIL = "api/iot/queryPositionTruckDetail";
    private static final String PATH_POSITION_TRUCK_COUNTS = "api/iot/queryPositionTruckSum";
    private static final String PATH_POSITION_TRUCK = "api/iot/queryPositionTruck";
    private static final String PATH_ORDER_STATISTICS = "api/iot/queryOrderStat";
    private static final String PATH_FLOWS_STATISTICS = "api/iot/queryOrderFlowStat";
    private static final String PATH_QUERY_ORDER_BY_NODE_TYPE = "api/iot/queryOrderByNodeType";
    private static final String PATH_QUERY_WAIT_TEST_CALL_TRUCK_LIST = "api/order/queryWaitTestCallTruckList";
    private static final String PATH_GET_POUND_QUEUE_INFO = "getPoundQueueInfo";


    private static final String PATH_STATION_QUERY = "api/transVss/stationQuery";
    private static final String PATH_TRUCK_QUERY = "api/transVss/truckQuery";
    private static final String PATH_CUSTOMER_QUERY = "api/transVss/customerQuery";

    private static final Integer SUCCESS_CODE = 200;

    @Override
    public VehicleScheduleResponseDTO onCheckingTruckEntry(VehicleScheduleIntegrationConfig config, VehicleScheduleRequestsDTO request) {
        JSONObject objects = onBuildingTruckParams(request);
        log.info("请求中交兴路的参数为：{}", JSONObject.toJSONString(objects));
        JSONObject result = new JSONObject();

        //查看是否是用于车辆调度的测试环境的车牌号
        List<String> vehicleString = Arrays.asList(config.getVehicleTest().split(","));
        if(vehicleString.contains(request.getTruckNo()) && StringUtils.isNotEmpty(request.getTruckNo())){
            result = executeVSSTest(config, PATH_ENTER_CHECKS, objects);
        }else {
            result = executeVSS(config, PATH_ENTER_CHECKS, objects);
        }

        if (result.getIntValue("code") != 200) {
            throw new IntegrationZoneException(result.getString("msg"));
        }
        if("Y".equals(result.get("data"))){
            return new VehicleScheduleResponseDTO();
        }
        VehicleScheduleResponseDTO vehicleScheduleResponseDTO = result.getJSONObject("data").toJavaObject(VehicleScheduleResponseDTO.class);
        vehicleScheduleResponseDTO.setWeightType(result.getJSONObject("data").getString("weightingType"));
        return vehicleScheduleResponseDTO;
    }

    @Override
    public VehicleScheduleResponseDTO onSyncingTruckEvents(VehicleScheduleIntegrationConfig config, VehicleScheduleRequestsDTO request) {
        JSONObject objects = onBuildingTruckParams(request);
        log.info("请求中交兴路的参数为：{}", JSONObject.toJSONString(objects));
        JSONObject result = new JSONObject();

        //查看是否是用于车辆调度的测试环境的车牌号
        List<String> vehicleString = Arrays.asList(config.getVehicleTest().split(","));
        if(vehicleString.contains(request.getTruckNo()) && StringUtils.isNotEmpty(request.getTruckNo())){
            result = executeVSSTest(config, PATH_TRUCK_EVENTS, objects);
        }else {
            result = executeVSS(config, PATH_TRUCK_EVENTS, objects);
        }

        if (result.getIntValue("code") != 200) {
            throw new IntegrationZoneException(result.getString("msg"));
        }
        if("Y".equals(result.get("data"))){
            return new VehicleScheduleResponseDTO();
        }
        VehicleScheduleResponseDTO vehicleScheduleResponseDTO = result.getJSONObject("data").toJavaObject(VehicleScheduleResponseDTO.class);
        vehicleScheduleResponseDTO.setWeightType(result.getJSONObject("data").getString("weightingType"));
        return vehicleScheduleResponseDTO;
    }

    @Override
    public VehicleScheduleResponseDTO onSyncingSpaceStatus(VehicleScheduleIntegrationConfig config, VehicleScheduleRequestsDTO request) {
        JSONObject objects = onBuildingTruckParams(request);
        log.info("请求中交兴路的参数为：{}", JSONObject.toJSONString(objects));
        JSONObject result = new JSONObject();

        //查看是否是用于车辆调度的测试环境的车牌号
        List<String> vehicleString = Arrays.asList(config.getVehicleTest().split(","));
        if(vehicleString.contains(request.getTruckNo()) && StringUtils.isNotEmpty(request.getTruckNo())){
            result = executeVSSTest(config, PATH_SPACE_STATUS, objects);
        }else {
            result = executeVSS(config, PATH_SPACE_STATUS, objects);
        }

        if (result.getIntValue("code") != 200) {
            throw new IntegrationZoneException(result.getString("msg"));
        }
        if("Y".equals(result.get("data"))){
            return new VehicleScheduleResponseDTO();
        }
        VehicleScheduleResponseDTO vehicleScheduleResponseDTO = result.getJSONObject("data").toJavaObject(VehicleScheduleResponseDTO.class);
        vehicleScheduleResponseDTO.setWeightType(result.getJSONObject("data").getString("weightingType"));
        return vehicleScheduleResponseDTO;
    }

    /**
     * 构建车辆事件请求体
     */
    private JSONObject onBuildingTruckParams(VehicleScheduleRequestsDTO request) {
        JSONObject params = new JSONObject();
        if(request.getTransportOrderCode() != null){
            params.put("transportOrderCode", request.getTransportOrderCode());
        }

        JSONObject position = new JSONObject();
        if(StringUtils.isNotEmpty(request.getPositionId())){
            position.put("positionId", request.getPositionId());
        }
        if(StringUtils.isNotEmpty(request.getPositionType())){
            position.put("positionType", request.getPositionType());
        }
        if(StringUtils.isNotEmpty(request.getPositionName())){
            position.put("positionName", request.getPositionName());
        }
        params.put("position", position);

        JSONObject device = new JSONObject();
        if(StringUtils.isNotEmpty(request.getDeviceName())){
            device.put("deviceName", request.getDeviceName());
        }
        if(StringUtils.isNotEmpty(request.getSerialNumber())){
            device.put("serialNumber", request.getSerialNumber());
        }
        if(StringUtils.isNotEmpty(request.getDeviceType())){
            device.put("deviceType", request.getDeviceType());
        }
        params.put("device", device);

        if(StringUtils.isNotEmpty(request.getPo())){
            params.put("poId", request.getPo());
        }

        if(StringUtils.isNotEmpty(request.getCommandId())){
            params.put("commandId", request.getCommandId());
        }

        JSONObject truck = new JSONObject();
        if(StringUtils.isNotEmpty(request.getTruckId())){
            truck.put("truckId", request.getTruckId());
        }
        if(StringUtils.isNotEmpty(request.getTruckNo())){
            truck.put("truckNo", request.getTruckNo());
        }
        if(StringUtils.isNotEmpty(request.getPlateColor())){
            truck.put("plateColor", request.getPlateColor());
        }
        params.put("truck", truck);

        JSONObject event = new JSONObject();
        if(StringUtils.isNotEmpty(request.getEventType())){
            event.put("eventType", request.getEventType());
        }
        event.put("eventTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        params.put("event", event);

        return params;
    }

    @Override
    public VehicleScheduleResponseDTO onSyncingWeighResult(VehicleScheduleIntegrationConfig config, VehicleScheduleRequestsDTO request) {
        JSONObject objects = onBuildingTruckParams(request);

        JSONObject weigh = new JSONObject();
        weigh.put("weightId", request.getWeightId());
        weigh.put("weightNumber", request.getWeightNumber());
        weigh.put("weightType", request.getWeightType());
        weigh.put("weight", request.getWeight());
        weigh.put("unit", request.getUnit().toUpperCase());
        weigh.put("weighTime", request.getWeighTime());
        weigh.put("operateUserId", request.getOperateUserId());
        objects.put("weigh", weigh);

        log.info("请求中交兴路的参数为：{}", JSONObject.toJSONString(objects));
        JSONObject result = new JSONObject();

        //查看是否是用于车辆调度的测试环境的车牌号
        List<String> vehicleString = Arrays.asList(config.getVehicleTest().split(","));
        if(vehicleString.contains(request.getTruckNo()) && StringUtils.isNotEmpty(request.getTruckNo())){
            result = executeVSSTest(config, PATH_WEIGH_EVENTS, objects);
        }else {
            result = executeVSS(config, PATH_WEIGH_EVENTS, objects);
        }

        if (result.getIntValue("code") != 200) {
            throw new IntegrationZoneException(result.getString("msg"));
        }
        if("Y".equals(result.get("data"))){
            return new VehicleScheduleResponseDTO();
        }
        VehicleScheduleResponseDTO vehicleScheduleResponseDTO = result.getJSONObject("data").toJavaObject(VehicleScheduleResponseDTO.class);
        vehicleScheduleResponseDTO.setWeightType(result.getJSONObject("data").getString("weightingType"));
        return vehicleScheduleResponseDTO;
    }

    @Override
    public List<VehicleScheduleResponseDTO> onListingQueue(VehicleScheduleIntegrationConfig config, VehicleScheduleRequestsDTO request) {
        JSONObject params = new JSONObject();
        params.put("orderType", "NONE");
        JSONObject result = executeVSS(config, PATH_QUEUE_DETAIL, params);
        if (result.getIntValue("code") != 200) {
            return Collections.emptyList();
        }
        List<VehicleScheduleResponseDTO> targets = new LinkedList<>();
        JSONArray array = result.getJSONArray("dataList");
        for (int position = 0; position < array.size(); position++) {
            VehicleScheduleResponseDTO target = array.getJSONObject(position).toJavaObject(VehicleScheduleResponseDTO.class);
            targets.add(target);
        }
        return targets;
    }

    @Override
    public List<VehicleScheduleStatisticsResponseDTO> onQueryPositionTruckQueues(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) {
        JSONObject objects = new JSONObject();
        objects.put("createStartTime", request.getStartTime());
        objects.put("createEndTime", request.getEndTime());
        objects.put("orderType", request.getOrderType());
        objects.put("positionId", request.getPositionId());
        JSONObject result = executeTMS(config, PATH_POSITION_TRUCK_QUEUES, objects);

        if (!"Y".equals(result.getString("returnCode"))) {
            throw new IntegrationZoneException(result.getString("returnInfo"));
        }
        List<SinoiovStatisticsResponseDTO> dtos = result.getJSONArray("obj").toJavaList(SinoiovStatisticsResponseDTO.class);
        return dtos.stream().map(dto -> {
            VehicleScheduleStatisticsResponseDTO target = new VehicleScheduleStatisticsResponseDTO();
            BeanUtils.copyProperties(dto, target);
            return target;
        }).collect(Collectors.toList());
    }

    @Override
    public List<VehicleScheduleStatisticsResponseDTO> onQueryPositionTruckDetail(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) {
        JSONObject objects = new JSONObject();
        objects.put("createStartTime", request.getStartTime());
        objects.put("createEndTime", request.getEndTime());
        objects.put("orderType", request.getOrderType());
        objects.put("positionId", request.getPositionId());
        objects.put("parentPositionId",request.getParentPositionId());
        JSONObject result = executeTMS(config, PATH_POSITION_TRUCK_DETAIL, objects);

        if (!"Y".equals(result.getString("returnCode"))) {
            throw new IntegrationZoneException(result.getString("returnInfo"));
        }
        List<SinoiovStatisticsResponseDTO> dtos = result.getJSONArray("obj").toJavaList(SinoiovStatisticsResponseDTO.class);
        return dtos.stream().map(dto -> {
            VehicleScheduleStatisticsResponseDTO target = new VehicleScheduleStatisticsResponseDTO();
            BeanUtils.copyProperties(dto, target);
            return target;
        }).collect(Collectors.toList());
    }

    @Override
    public List<VehicleScheduleStatisticsResponseDTO> onQueryPositionTruckCounts(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) {
        JSONObject objects = new JSONObject();
        objects.put("createStartTime", request.getStartTime());
        objects.put("createEndTime", request.getEndTime());
        objects.put("orderType", request.getOrderType());
        objects.put("positionId", request.getPositionId());
        JSONObject result = executeTMS(config, PATH_POSITION_TRUCK_COUNTS, objects);

        if (!"Y".equals(result.getString("returnCode"))) {
            throw new IntegrationZoneException(result.getString("returnInfo"));
        }
        List<SinoiovStatisticsResponseDTO> dtos = result.getJSONArray("obj").toJavaList(SinoiovStatisticsResponseDTO.class);
        return dtos.stream().map(dto -> {
            VehicleScheduleStatisticsResponseDTO target = new VehicleScheduleStatisticsResponseDTO();
            BeanUtils.copyProperties(dto, target);
            return target;
        }).collect(Collectors.toList());
    }

    @Override
    public List<VehicleScheduleStatisticsResponseDTO> onQueryPositionTruck(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) {
        JSONObject objects = new JSONObject();
        objects.put("createStartTime", request.getStartTime());
        objects.put("createEndTime", request.getEndTime());
        objects.put("orderType", request.getOrderType());
        objects.put("positionId", request.getPositionId());
        JSONObject result = executeTMS(config, PATH_POSITION_TRUCK, objects);

        if (!"Y".equals(result.getString("returnCode"))) {
            throw new IntegrationZoneException(result.getString("returnInfo"));
        }
        List<SinoiovStatisticsResponseDTO> dtos = result.getJSONArray("obj").toJavaList(SinoiovStatisticsResponseDTO.class);
        return dtos.stream().map(dto -> {
            VehicleScheduleStatisticsResponseDTO target = new VehicleScheduleStatisticsResponseDTO();
            BeanUtils.copyProperties(dto, target);
            return target;
        }).collect(Collectors.toList());
    }

    @Override
    public List<VehicleScheduleStatisticsResponseV2DTO> onQueryOrderStatistics(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) {
        JSONObject objects = new JSONObject();
        objects.put("createStartTime", request.getStartTime());
        objects.put("createEndTime", request.getEndTime());
        objects.put("orderType", request.getOrderType());
//        objects.put("positionId", request.getPositionId());
        JSONObject result = executeTMS(config, PATH_ORDER_STATISTICS, objects);

        if (!"Y".equals(result.getString("returnCode"))) {
            throw new IntegrationZoneException(result.getString("returnInfo"));
        }
        return result.getJSONArray("obj").toJavaList(VehicleScheduleStatisticsResponseV2DTO.class);
    }

    @Override
    public List<VehicleScheduleOrderFlowStateResponseDTO> onQueryFlowsStatistics(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) {
        JSONObject objects = new JSONObject();
        objects.put("createStartTime", request.getStartTime());
        objects.put("createEndTime", request.getEndTime());
        objects.put("orderTypeList", request.getOrderTypeList());
        JSONObject result = executeTMS(config, PATH_FLOWS_STATISTICS, objects);

        if (!"Y".equals(result.getString("returnCode"))) {
            throw new IntegrationZoneException(result.getString("returnInfo"));
        }
        return result.getJSONArray("obj").toJavaList(VehicleScheduleOrderFlowStateResponseDTO.class);
    }


    @Override
    public List<VehicleScheduleResponseV2DTO> onQueryOrderFlowState(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request){
        JSONObject objects = new JSONObject();
        objects.put("createStartTime", request.getStartTime());
        objects.put("createEndTime", request.getEndTime());
        objects.put("orderType", request.getOrderType());
        objects.put("nodeTypeList", request.getNodeTypeList());
        JSONObject result = executeTMS(config, PATH_QUERY_ORDER_BY_NODE_TYPE, objects);

        if (!"Y".equals(result.getString("returnCode"))) {
            throw new IntegrationZoneException(result.getString("returnInfo"));
        }
        return result.getJSONArray("obj").toJavaList(VehicleScheduleResponseV2DTO.class);
    }

    @Override
    public List<VehicleScheduleWaitTestCallTruckDTO> onQueryWaitTestCallTruckList(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) {

        JSONObject result = executeVSS(config, PATH_QUERY_WAIT_TEST_CALL_TRUCK_LIST, new JSONObject());

        if (!SUCCESS_CODE.equals(result.getInteger("code"))) {
            throw new IntegrationZoneException(result.getString("msg"));
        }
        return result.getJSONArray("dataList").toJavaList(VehicleScheduleWaitTestCallTruckDTO.class);
    }

    @Override
    public List<VehicleSchedulePoundQueueInfoDTO> onQueryPoundQueueInfo(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) throws Exception {

        JSONObject result = executeVssForGet(config, PATH_GET_POUND_QUEUE_INFO, new JSONObject());

        if (!SUCCESS_CODE.equals(result.getInteger("code"))) {
            throw new IntegrationZoneException(result.getString("msg"));
        }
        return result.getJSONArray("dataList").toJavaList(VehicleSchedulePoundQueueInfoDTO.class);
    }

    @Override
    public List<StationDTO> stationQuery(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) {
        JSONObject objects = new JSONObject();
        objects.put("requestTime", request.getStartTime());
        objects.put("positionId", request.getPositionId());
        JSONObject result = executeWMS(config, PATH_STATION_QUERY, objects);

        if (result.getIntValue("code") != 200) {
            throw new IntegrationZoneException(result.getString("message"));
        }
        List<StationDTO> dtos = result.getJSONArray("data").toJavaList(StationDTO.class);
        return dtos;
    }

    @Override
    public List<TruckQueryResponseDTO> truckQuery(VehicleScheduleIntegrationConfig config, VehicleScheduleStatisticsRequestsDTO request) {
        JSONObject objects = new JSONObject();
        objects.put("requestTime", request.getStartTime());
        JSONObject result = executeWMS(config, PATH_TRUCK_QUERY, objects);

        if (result.getIntValue("code") != 200) {
            throw new IntegrationZoneException(result.getString("message"));
        }
        List<TruckQueryResponseDTO> dtos = result.getJSONArray("data").toJavaList(TruckQueryResponseDTO.class);
        return dtos;
    }
}
